#import "AppController.h"
#import "Picker.h"

//CONSTANTS:
#define kNumPads			1
#define kAppIdentifier		@"ac3d"
#define kAccelReadingId 1
#define kTouchesBeganId 2
#define kTouchesMovedId 3

//INTERFACES:

@interface AppController ()
- (void) setup;
- (void) presentPicker:(NSString*)name;
@end

//CLASS IMPLEMENTATIONS:

@implementation AppController

- (void) _showAlert:(NSString*)title
{
	/*
	UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:title message:@"Check your networking configuration." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
	[alertView show];
	[alertView release];
	 */
	[self setup];
}

- (void) applicationDidFinishLaunching:(UIApplication*)application
{
	CGRect					rect;
	UIView*					view;
	NSUInteger				x,
							y;
	_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
	[_window setBackgroundColor:[UIColor darkGrayColor]];
	
	rect = [[UIScreen mainScreen] applicationFrame];
	for(y = 0; y < kNumPads; ++y) {
		for(x = 0; x < kNumPads; ++x) {
			view = [[TapView alloc] initWithFrame:CGRectMake(rect.origin.x + x * rect.size.width / (float)kNumPads, rect.origin.y + y * rect.size.height / (float)kNumPads, rect.size.width / (float)kNumPads, rect.size.height / (float)kNumPads)];
			[view setMultipleTouchEnabled:NO];
			[view setBackgroundColor:[UIColor colorWithHue:((y * kNumPads + x) / (float)(kNumPads * kNumPads)) saturation:0.75 brightness:0.75 alpha:1.0]];
			[view setTag:(y * kNumPads + x + 1)];
			[_window addSubview:view];
			[view release];
		}
	}
    
	 
	//Show the window
	[_window makeKeyAndVisible];
	
	[[UIAccelerometer sharedAccelerometer] setUpdateInterval:.05];
	[[UIAccelerometer sharedAccelerometer] setDelegate:self];
	
	[self setup];
}

- (void) dealloc
{	
	[_inStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
	[_inStream release];

	[_outStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
	[_outStream release];

	[_picker release];
	
	[_window release];
	
	[super dealloc];
}

- (void) setup {
	
	[_inStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
	[_inStream release];
	_inStream = nil;
	_inReady = NO;

	[_outStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
	[_outStream release];
	_outStream = nil;
	_outReady = NO;
	
	[self presentPicker:nil];
}

- (NSString*) bonjourTypeFromIdentifier:(NSString*)identifier {
	if (![identifier length])
		return nil;
    
    return [NSString stringWithFormat:@"_%@._tcp.", identifier];
}

- (void) presentPicker:(NSString*)name {
	if (!_picker) {
		_picker = [[Picker alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] type:[self bonjourTypeFromIdentifier:kAppIdentifier]];
		_picker.delegate = self;
	}
	
	_picker.gameName = name;

	if (!_picker.superview) {
		[_window addSubview:_picker];
	}
}

- (void) destroyPicker {
	[_picker removeFromSuperview];
	[_picker release];
	_picker = nil;
}

- (void) alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
	[self setup];
}

- (void) send:(const uint8_t)message
{
	/*
	if (_outStream && [_outStream hasSpaceAvailable])
		if([_outStream write:(const uint8_t *)&message maxLength:sizeof(const uint8_t)] == -1)
			[self _showAlert:@"Failed sending data to peer"];

	 */
}

- (void) openStreams
{
	_inStream.delegate = self;
	[_inStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
	[_inStream open];
	_outStream.delegate = self;
	[_outStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
	[_outStream open];
}

- (void) browserViewController:(BrowserViewController*)bvc didResolveInstance:(NSNetService*)netService
{
	if (!netService) {
		[self setup];
		return;
	}

	if (![netService getInputStream:&_inStream outputStream:&_outStream]) {
		[self _showAlert:@"Failed connecting to server"];
		return;
	}

	[self openStreams];
}

- (void) sendTouches:(NSSet*)touches withEvent:(UIEvent*)event withId:(uint8_t)ident
{
	float buffer[2];
	UITouch *touch = [touches anyObject];	
	CGPoint touchLocation = [touch locationInView: [touch view]];
	
	buffer[0] = touchLocation.x;
	buffer[1] = touchLocation.y;
	
	if (_outStream && [_outStream hasSpaceAvailable]) {
		if([_outStream write:(const uint8_t *)&ident maxLength:sizeof(ident)] == -1) {
			[self _showAlert:@"Failed sending data to peer"];
		}
		if([_outStream write:(const uint8_t *)&buffer maxLength:sizeof(buffer)] == -1) {
			[self _showAlert:@"Failed sending data to peer"];
		}
	}
	
}

- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
	[self sendTouches:touches withEvent:event withId:kTouchesBeganId];
}

- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
	[self sendTouches:touches withEvent:event withId:kTouchesMovedId];
}

@end

@implementation AppController (NSStreamDelegate)

- (void) stream:(NSStream*)stream handleEvent:(NSStreamEvent)eventCode
{
	switch(eventCode) {
		case NSStreamEventOpenCompleted:
		{
			[self destroyPicker];

			if (stream == _inStream)
				_inReady = YES;
			else
				_outReady = YES;
			
			if (_inReady && _outReady) {
				/*
				alertView = [[UIAlertView alloc] initWithTitle:@"Game started!" message:nil delegate:nil cancelButtonTitle:nil otherButtonTitles:@"Continue", nil];
				[alertView show];
				[alertView release];
				 */
			}
			break;
		}
	}
}

@end

@implementation AppController(UIAccelerometerDelegate)

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
	uint8_t ident = kAccelReadingId;
	float buffer[3];
	buffer[0] = acceleration.x;
	buffer[1] = acceleration.y;
	buffer[2] = acceleration.z;
	
	if (_outStream && [_outStream hasSpaceAvailable]) {
		if([_outStream write:(const uint8_t *)&ident maxLength:sizeof(ident)] == -1) {
			[self _showAlert:@"Failed sending data to peer"];
		}
		if([_outStream write:(const uint8_t *)&buffer maxLength:sizeof(buffer)] == -1) {
			[self _showAlert:@"Failed sending data to peer"];
		}
	}
}

@end
